<Serializable()> _
Public Class BetweenCriteria
    Implements ICriteriaComponent

    Protected mLeftExpression As String
    Protected mLowExpression As String
    Protected mHighExpression As String

    Public Property LeftExpression() As String
        Get
            Return mLeftExpression
        End Get
        Set(ByVal value As String)
            mLeftExpression = value
        End Set
    End Property

    Public Property LeftExpressionType As ExpressionType = ExpressionType.Auto

    Public Property LowExpression() As String
        Get
            Return mLowExpression
        End Get
        Set(ByVal value As String)
            mLowExpression = value
        End Set
    End Property

    Public Property LowExpressionType As ExpressionType = ExpressionType.Auto

    Public Property HighExpression() As String
        Get
            Return mHighExpression
        End Get
        Set(ByVal value As String)
            mHighExpression = value
        End Set
    End Property

    Public Property HighExpressionType As ExpressionType = ExpressionType.Auto

    Public Sub New()
    End Sub
    Public Sub New(ByVal LeftExpression As String, ByVal LowExpression As String, ByVal HighExpression As String)
        mLeftExpression = LeftExpression
        mLowExpression = LowExpression
        mHighExpression = HighExpression
    End Sub

    Public Function GetText() As String Implements ICriteriaComponent.GetText
        Return GetText(QueryOptions.DefaultOptions)
    End Function

    Public Function GetText(Options As QueryOptions) As String Implements ICriteriaComponent.GetText

        Dim Quote1 As Boolean = True
        Dim Quote2 As Boolean = True

        If DatabaseTypeHelper.LooksLikeParam(mLowExpression, Options) Then Quote1 = False
        If DatabaseTypeHelper.LooksLikeParam(mHighExpression, Options) Then Quote2 = False


        Dim ret As String = PrepLeftExpr(mLeftExpression, Options) & " BETWEEN " & PrepRightExpr(mLowExpression, LowExpressionType, Options) & " AND " & PrepRightExpr(mHighExpression, HighExpressionType, Options)

        Return ret

    End Function

    Private Function PrepLeftExpr(Expression As String, options As QueryOptions) As String
        If LeftExpressionType = ExpressionType.Exact Then
            Return Expression
        End If

        Dim ret As String = ""

        Dim UseQuotes As Boolean = False
        Dim Escape As Boolean = False
        If LeftExpressionType = ExpressionType.Literal AndAlso Not IsNumeric(Expression) Then
            UseQuotes = True
            Escape = True
        End If

        If Escape Then
            Expression = Expression.Replace("'", "''")
        End If

        ret = If(UseQuotes, "'", "") & Expression & If(UseQuotes, "'", "")

        Return ret
    End Function

    Private Function PrepRightExpr(Expression As String, ExpressionType As ExpressionType, options As QueryOptions) As String
        Dim ret As String = ""

        Dim UseQuotes As Boolean = True
        Dim Escape As Boolean = False
        Select Case ExpressionType
            Case QBuilder.ExpressionType.Auto
                If DatabaseTypeHelper.LooksLikeParam(Expression, options) OrElse IsNumeric(Expression) Then
                    UseQuotes = False
                End If
            Case QBuilder.ExpressionType.Literal
                If IsNumeric(Expression) Then
                    UseQuotes = False
                    Escape = True
                End If
            Case QBuilder.ExpressionType.Logical
                UseQuotes = False
            Case QBuilder.ExpressionType.Exact
                Return Expression
        End Select

        If Escape Then
            Expression = Expression.Replace("'", "''")
        End If

        ret = If(UseQuotes, "'", "") & Expression & If(UseQuotes, "'", "")

        Return ret
    End Function

    Public ReadOnly Property ShouldRender() As Boolean Implements ICriteriaComponent.HasContent
        Get
            Return True
        End Get
    End Property
End Class
